package ude.univ.esiag.gon.uchiha.core;

import ude.univ.esiag.gon.uchiha.operation.Operation;
import ude.univ.esiag.gon.uchiha.reader.DataReaderClient;
import ude.univ.esiag.gon.uchiha.register.MulticasterClient;
import ude.univ.esiag.gon.uchiha.subscriber.Semaphore;
import ude.univ.esiag.gon.uchiha.subscriber.Subscriber;
import ude.univ.esiag.gon.uchiha.subscriber.impl.SubscriberImpl;
import ude.univ.esiag.gon.uchiha.writer.DataWriter;


public class DCSClient {
	private DataReaderClient dr;
	private static DCSClient singleton;
	private DataWriter dw = null;
	private String topicName;
	private String SubscriberIOR;
	private Semaphore semaphoreW;
	private Semaphore semaphoreR;
	private Semaphore semaphoreD;
	private Object data;
	private DCSClient() {
		semaphoreW = new Semaphore(0);
		semaphoreR = new Semaphore(0);
		semaphoreD = new Semaphore(0);
	}
	synchronized public Object read(){
		if(dw == null){
			semaphoreR.stop();
		}
		Operation operation = new Operation(topicName, SubscriberIOR);
		operation.setTarget(Operation.CACHE);
		operation.setType(Operation.READ);
		operation.setToReplicate(false);
		dw.write(operation);
		if(data == null){
			semaphoreD.stop();
		}
		Object data = this.data;
		this.data = null;
		return data;
	}
	public void setData(Object data) {
		this.data = data;
		semaphoreD.signal();
	}
	public void createTopic(String SimpleName){
		Operation operation = new Operation(topicName, SimpleName);
		operation.setTarget(Operation.TOPIC);
		operation.setType(Operation.CREATES);
		operation.setToReplicate(true);
		write(operation);
	}
	synchronized private void write(Operation operation){
		if(dw == null){
			semaphoreW.stop();
		}
		dw.write(operation);
	}
	synchronized public void write(Object obj){
		Operation operation = new Operation(topicName, obj);
		operation.setTarget(Operation.CACHE);
		operation.setType(Operation.WRITE);
		operation.setToReplicate(true);
		write(operation);
	}
	public void setDataWriter(Subscriber subscriber){
		dw = new DataWriter();
		dw.addSubscriber(subscriber);
		semaphoreW.signal();
		semaphoreR.signal();
	}
	public static DCSClient getInstance(){
		if(singleton == null){
			singleton = new DCSClient();
		}
		return singleton;
	}
	public boolean isWritable(){
		return dw != null;
	}
	synchronized public void init(String topicName){
		this.topicName = topicName;
		dw = null;
		dr = new DataReaderClient(topicName);
		SubscriberImpl subscriber = dr.getSubscriber();
		SubscriberIOR = MulticasterClient.getInstance().subscriber_to_ior(subscriber);
		MulticasterClient.getInstance().broadcast(topicName, SubscriberIOR);
	}
}
